from public import getResultDf, getAnalysis, save_log
from spice.circuit import Circuit
from matplotlib import pyplot as plt
from spice.circuit import Circuit
from PIL import Image
import io
from loguru import logger
import re
import gradio as gr

    
def _color(texts, is_err)->str:
    return '\n'.join(f"{'❌' if is_err else '⚠️'} {text}" for text in texts)

# 上传的多个文件处于不同的文件夹下
def translate(files, request: gr.Request):
    assert files, "请上传文件"
    filepaths = [file.name for file in files]  # 获取上传的文件路径
    circuit = Circuit()
    warns,errs = circuit.init(*filepaths)
    # 节点 
    nodes = [node.symbol for node in circuit.node_map.values() if node.is_valid]
    # 组件
    cs = [c.symbol for c in circuit.component_map.values()]
    save_log( '转为spice脚本', request)
    return circuit, str(circuit), _color(warns, False)+'\n'+_color(errs, True),cs, nodes, gr.update(visible=True)

def _update_run(circuit, analysis, ml, select:list):
    # 使用 pandas 读取数据（自动识别空格分隔）
    try:
        df,log,run_text = getResultDf(circuit, analysis, select, ml)
        assert df is not None, '无法获取结果'
        x,y = (len(select)+1)//2, min(len(select),2)
        _, axs = plt.subplots(x,y, figsize=(28, 10))
        for i, lie in enumerate(select):
            if len(select) == 1:
                ax = axs
            else:
                match axs.shape:
                    case (q,w): ax = axs[i//2, i%2]
                    case (q,):  ax = axs[i]
            ax.plot(df.iloc[:,i*2], df.iloc[:,i*2+1])
            liex, liey=df.columns[i*2], df.columns[i*2+1]
            ax.set_xlabel(liex)
            ax.set_ylabel(liey)
        buf = io.BytesIO()
        plt.savefig(buf, format='png')
        plt.close()
        buf.seek(0)
        img = Image.open(buf)
    except Exception as e:
        logger.error(f'绘图失败-{e}')
        img=None
    return img, log, run_text

# 更新对应脚本+执行可视化
def update_run(net0:str,initial:str,select:list[str],vselect:list[str],vcontent:str,analysis:str,
                *opt):
    assert net0, '请先上传网表信息'
    assert select, '未选择需要查看的信息'
    assert analysis, '请选择分析模式'    
    if vselect: 
        assert vcontent, '模拟电压值未填写'
        # 直流电压
        if re.match(r'\d+$', vcontent): vcontent = f'DC {vcontent}' 
        net = '\n'.join([net0, '* 模拟电压源',*[f'Vsimulate{i+1} {vt} 0 {vcontent}' for i,vt in enumerate(vselect)]])
    else:
        net = net0
    ml=''
    match analysis:
        case '瞬态分析':
            analysis_text = f'.tran {opt[1]}ms {opt[0]}ms'
        case '交流分析':
            analysis_text = f'.ac {opt[0]} {opt[1]} {opt[2]} {opt[3]}'
        case '直流扫描':
            analysis_text = f'.dc {opt[0]} {opt[1]} {opt[2]} {opt[3]}'
        case '快速傅里叶':
            analysis_text = f'.tran {opt[1]}ms {opt[0]}ms'
            ml = ' '.join(['fft',*opt[2]])
    text = getAnalysis(analysis_text, initial, probe=' '.join([t for t in select if t.startswith('I')]))
    img, result, run_text = _update_run(net,text,ml,select)
    return text, run_text, result, img